package auditoryUI;

import java.util.Timer;
import java.util.TimerTask;


public class SimpleStrokeAudioUI {

	//creating four values that the systems will read. 
	private static int _rawx, _rawy, _rawz, _x, _y, _z, _button, _lastZ, _lastEvent,
			_x0, _y0;
	
//	for sensing the signals
	static final int miDelay = 100;
	//	 repeat every sec.
	static final int miPeriod = 20;
	
	private int oldButton = -1;
	
	
	public static double mdStartAngle = Math.toDegrees(Math.PI / 8.0 + Math.PI
			/ 2.0);

	//	Timer to check for touchpad positions from the C++ dll
	private Timer fingerDetector = new java.util.Timer();
	
	public SimpleStrokeAudioUI(SimpleTouchpadInterface sd){
		try {
			System.loadLibrary("simpletpinfoJava");
		} catch (UnsatisfiedLinkError ule) {
			System.out.println(ule);
			System.exit(0);
		}
		initTouchPad();
		TimerTask pullingTask = new TouchPadMonitor(sd);
		fingerDetector.scheduleAtFixedRate(pullingTask, miDelay, miPeriod);
	}

	
	//native methods to check the touchpad coordinates 
	public native void initTouchPad();

	public native void terminateTouchPad();

	public native void readTouchPadValues(int[] values);

	
	/**
	 * This class check the touch pad input frequently.
	 * @author Stephen
	 *
	 */
	private class TouchPadMonitor extends TimerTask {
		
		
		private SimpleTouchpadInterface sd;
		
		public TouchPadMonitor(SimpleTouchpadInterface sd){
			this.sd = sd;
		}

		
		public void run() {

			//need to check to see if the x, y position of the mouse has been moved or not	
			// Task here
			int values[] = new int[4];
			readTouchPadValues(values);
			//			System.out.print("R");
			if (values[0] == _rawx && values[1] == _rawy && values[2] == _rawz
					&& values[3] == _button) {
				return;
			}

			_rawx = values[0];
			_rawy = values[1];
			_rawz = values[2];
			_x = values[0];
			_y = values[1];
			_z = values[2];
			//threshold here to filter input data
			if (Math.abs(_x - _x0) <= 10 || Math.abs(_y - _y0) <= 10){
				_x0 = _x;
				_y0 = _y;
				return;
			}
			_button = values[3];
			if (oldButton != _button && _button != 0) {
					sd.touchpadButtonPressed(_button);
					oldButton = _button;
			} else if (_button == 0 && oldButton != -1) {
					sd.touchpadButtonReleased(oldButton);
					oldButton = -1;
			}
			
			if (_x > Constants.TP_HMAX)
				_x = Constants.TP_HMAX;
			if (_x < Constants.TP_HMIN) 
				_x = Constants.TP_HMIN;
			if (_y > Constants.TP_VMAX)
				_y = Constants.TP_VMAX;
			if (_y < Constants.TP_VMIN)
				_y = Constants.TP_VMIN;

			//2. second step, perform the translation
			_x = _x - Constants.TP_HMIN;
			_y = _y - Constants.TP_VMIN;

			//2.5 translation so the center of the rect is the origin
			_x = _x - (Constants.TP_HMAX - Constants.TP_HMIN) / 2;
			_y = _y - (Constants.TP_VMAX - Constants.TP_VMIN) / 2;

			//3. perform the rotation
			double angle = 0;
			switch (Constants.TOUCHPAD_ORIENTATION) {
			case Constants.NORTH:
				angle = 0.0;
				break;
			case Constants.EAST:
				angle = (Math.PI / 2.0);
				break;
			case Constants.SOUTH:
				angle = (Math.PI);
				break;
			case Constants.WEST:
				angle = -(Math.PI + Math.PI / 2.0);
				break;
			}

			double tmpX = (Math.cos(angle) * _x - Math.sin(angle) * _y);
			double tmpY = (Math.sin(angle) * _x + Math.cos(angle) * _y);

			//4. translate back
			//notice that when translate back, the x increment and y
			// increment have been swapped
			_x = (int) tmpX + (Constants.TP_VMAX - Constants.TP_VMIN) / 2;
			_y = (int) tmpY + (Constants.TP_HMAX - Constants.TP_HMIN) / 2;

			//well, because this operates in a thread, sometimes, certain events
			//will be missed, due to occasionally lose of data.
			//so we need to perform some checking to make sure everything happens logically
			//for example, an empty event should happen after a drag event, or touch event. 
			//since that means we skipped release. 
			if (_z == 0 && _lastZ == 0) {
				_lastEvent = 0;
				//1 and 2 represent touch or dragged
				if (_lastEvent == 1 || _lastEvent == 2) {
					//we need to add the finger released event here
					//debug("it happened *****************************************");
					sd.fingerReleasedCircle(_x, _y, _button, _z, _x0, _y0);
					_lastEvent = 3;
				}
				//need to check for last state, if the last event is 
			} else if (_z != 0 && _lastZ == 0) {
				_lastEvent = 1;
				//need to check last state 
				sd.fingerTouchedCircle(_x, _y, _button, _z);
			} else if (_z != 0 && _lastZ != 0) {
				_lastEvent = 2;
				//if last state is empty, need to insert 
				sd.fingerDraggedCircle(_x, _y, _button, _z, _x0, _y0);
			} else if (_z == 0 && _lastZ != 0) {
				_lastEvent = 3;
				sd.fingerReleasedCircle(_x, _y, _button, _z, _x0, _y0);
			}
			_x0 = _x;
			_y0 = _y;
			_lastZ = _z;
		}
	}
}
